En base a los datos de los accidentes de tráfico canadienses desde 1999 a 2014, se intenta predecir si una persona involucrada en un accidente fallecería.
Se tomarán las caracterisicas de los accidentes y de las personas involucradas para aplicar algoritmos de Machine Learning. Estos algoritmos aplicarán diferentes técnicas estadisticas y matemáticas para lograr obtener la mejor clasificación posible.
El motivo principal por el cual realizamos estas estimaciones es las aseguradoras tienen que inmovilizar capital para pagar estas casuísticas. Entonces, se busca minimizar el capital inmovilizado dado que se pierde la rentabilidad de tener el dinero invertido, sin afectar el hecho de que este dinero inmovilizado estará disponible para cubrir de alguna manera las necesidades de quienes sean afectados por estos hechos.
Los scripts utilizados para realizar esta solución son los siguientes y realizarán las tareas desarrollas:
# primero todas las librerías por bloques
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
sns.set()
import warnings
warnings.filterwarnings("ignore")
import statsmodels.api as sm
import plotly.express as px
import pickle
from random import seed
import plotly.graph_objects as go
from category_encoders import TargetEncoder
from sklearn.model_selection import train_test_split
from sklearn.impute import SimpleImputer
initial_data = pd.read_csv("../data/NCDB_1999_to_2014.csv",low_memory=False)
initial_data.head()
| C_YEAR | C_MNTH | C_WDAY | C_HOUR | C_SEV | C_VEHS | C_CONF | C_RCFG | C_WTHR | C_RSUR | ... | V_ID | V_TYPE | V_YEAR | P_ID | P_SEX | P_AGE | P_PSN | P_ISEV | P_SAFE | P_USER | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1999 | 01 | 1 | 20 | 2 | 02 | 34 | UU | 1 | 5 | ... | 01 | 06 | 1990 | 01 | M | 41 | 11 | 1 | UU | 1 |
| 1 | 1999 | 01 | 1 | 20 | 2 | 02 | 34 | UU | 1 | 5 | ... | 02 | 01 | 1987 | 01 | M | 19 | 11 | 1 | UU | 1 |
| 2 | 1999 | 01 | 1 | 20 | 2 | 02 | 34 | UU | 1 | 5 | ... | 02 | 01 | 1987 | 02 | F | 20 | 13 | 2 | 02 | 2 |
| 3 | 1999 | 01 | 1 | 08 | 2 | 01 | 01 | UU | 5 | 3 | ... | 01 | 01 | 1986 | 01 | M | 46 | 11 | 1 | UU | 1 |
| 4 | 1999 | 01 | 1 | 08 | 2 | 01 | 01 | UU | 5 | 3 | ... | 99 | NN | NNNN | 01 | M | 05 | 99 | 2 | UU | 3 |
5 rows × 22 columns
El conjunto de datos contiene variables que no estan disponibles para la aseguradora en el momento en que se presenta un anuncio de accidente en su plataforma. Estas deben eliminarse para realizar modelos ya que se estaría introduciendo información que el modelo en el momento en que lo queremos aplicar no tendría.
data = initial_data.drop(columns=['C_TRAF', 'C_RALN', 'P_ISEV'])
print('Dataset shape:',data.shape)
print('Dataset shape sin duplicados:',data.drop_duplicates().shape)
Dataset shape: (5860405, 19) Dataset shape sin duplicados: (5852815, 19)
Debemos no considerar registros duplicados ya que pueden modificar nuestro analisis
data = data.drop_duplicates()
y = data['C_SEV']
X = data.drop(columns=['C_SEV'])
xtrain, xtest, ytrain, ytest = train_test_split(X, y, test_size=0.25, random_state=0, stratify=y)
data = pd.concat([xtrain, ytrain], axis=1)
data_test = pd.concat([xtest, ytest], axis=1)
data.to_csv(r'../data/Untransformed_train_data_personal_prob.csv')
data_test.to_csv(r'../data/Untransformed_test_data_personal_prob.csv')
data.dtypes.to_dict()
{'C_YEAR': dtype('int64'),
'C_MNTH': dtype('O'),
'C_WDAY': dtype('O'),
'C_HOUR': dtype('O'),
'C_VEHS': dtype('O'),
'C_CONF': dtype('O'),
'C_RCFG': dtype('O'),
'C_WTHR': dtype('O'),
'C_RSUR': dtype('O'),
'V_ID': dtype('O'),
'V_TYPE': dtype('O'),
'V_YEAR': dtype('O'),
'P_ID': dtype('O'),
'P_SEX': dtype('O'),
'P_AGE': dtype('O'),
'P_PSN': dtype('O'),
'P_SAFE': dtype('O'),
'P_USER': dtype('O'),
'C_SEV': dtype('int64')}
data[['C_SEV']].info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 4389611 entries, 4850824 to 4137109 Data columns (total 1 columns): # Column Dtype --- ------ ----- 0 C_SEV int64 dtypes: int64(1) memory usage: 67.0 MB
objetivo = pd.DataFrame(data['C_SEV'].value_counts())
objetivo.columns = ['Acc con Fatalidades']
objetivo['Porcentaje'] = data['C_SEV'].value_counts()*100/len(data)
objetivo.reset_index(inplace=True)
objetivo.rename(columns={'index':'Values'}, inplace=True)
#objetivo
#objetivo.reset_index(inplace=True)
fig = px.bar(objetivo, x="Values", y=['Porcentaje', 'Acc con Fatalidades'])
fig.show();
y = pd.get_dummies(data['C_SEV'])
y.columns = ['Fatalities', 'No Fatalities']
data['C_SEV'] = y['Fatalities']
y = y['Fatalities']
y.value_counts()
0 4315651 1 73960 Name: Fatalities, dtype: int64
data.isnull().sum().sort_values(ascending=False)
C_VEHS 2 C_YEAR 0 V_TYPE 0 P_USER 0 P_SAFE 0 P_PSN 0 P_AGE 0 P_SEX 0 P_ID 0 V_YEAR 0 V_ID 0 C_MNTH 0 C_RSUR 0 C_WTHR 0 C_RCFG 0 C_CONF 0 C_HOUR 0 C_WDAY 0 C_SEV 0 dtype: int64
La variable 'C_VEHS' cuanta con la codificación para valores faltantes, rellenamos estos missing con el valor correspondiente
data.C_VEHS.fillna('UU', inplace=True)
data_test.C_VEHS.fillna('UU', inplace=True)
data.isnull().sum().sort_values(ascending=False)
C_YEAR 0 V_TYPE 0 P_USER 0 P_SAFE 0 P_PSN 0 P_AGE 0 P_SEX 0 P_ID 0 V_YEAR 0 V_ID 0 C_MNTH 0 C_RSUR 0 C_WTHR 0 C_RCFG 0 C_CONF 0 C_VEHS 0 C_HOUR 0 C_WDAY 0 C_SEV 0 dtype: int64
En primer lugar, observamos los valores captados por las variables numericas para detectar posibles outliers no desde un punto de vista estadistico, sino considerando valores no detallados en el diccionario de datos.
numerical_vars = ['C_YEAR', 'C_MNTH', 'C_WDAY', 'C_HOUR', 'P_ID', 'V_ID', 'V_YEAR', 'P_AGE']
pd.set_option("display.max_rows", 500)
for i in numerical_vars:
print(f'Cantidad de observaciones en: {str(data[[i]].columns.tolist()[0])}')
print('')
print(data[i].value_counts()/len(data))
#buscar que cuando haya algun U en el string, cuente en valores absolutos y relativos cuantos hay
print('')
print('-------------------')
Cantidad de observaciones en: C_YEAR 2000 0.071989 2002 0.071661 1999 0.070464 2001 0.069922 2003 0.069433 2004 0.066330 2005 0.065989 2006 0.064629 2007 0.062883 2008 0.057725 2010 0.057083 2009 0.056390 2011 0.055471 2012 0.055104 2013 0.054101 2014 0.050826 Name: C_YEAR, dtype: float64 ------------------- Cantidad de observaciones en: C_MNTH 08 0.093278 07 0.091844 12 0.089797 06 0.088732 10 0.087980 09 0.087579 01 0.085244 11 0.085061 05 0.079917 02 0.072237 03 0.071291 04 0.066972 UU 0.000067 Name: C_MNTH, dtype: float64 ------------------- Cantidad de observaciones en: C_WDAY 5 0.170591 4 0.148222 6 0.148070 3 0.140724 2 0.139378 1 0.132534 7 0.120253 U 0.000227 Name: C_WDAY, dtype: float64 ------------------- Cantidad de observaciones en: C_HOUR 16 0.088636 17 0.085378 15 0.083981 14 0.067831 18 0.064177 12 0.062817 13 0.062731 08 0.051658 11 0.051484 19 0.048130 10 0.042493 09 0.038911 20 0.037150 07 0.035448 21 0.034856 22 0.028113 23 0.021781 06 0.018059 00 0.015132 02 0.013192 01 0.012513 03 0.010937 UU 0.010120 05 0.007653 04 0.006818 Name: C_HOUR, dtype: float64 ------------------- Cantidad de observaciones en: P_ID 01 7.114291e-01 02 1.936030e-01 03 5.830790e-02 04 2.254437e-02 05 7.096529e-03 06 2.009745e-03 NN 1.874881e-03 07 8.356094e-04 08 3.834053e-04 09 2.378343e-04 10 1.913609e-04 11 1.535444e-04 12 1.364586e-04 13 1.118550e-04 14 9.271892e-05 15 8.292307e-05 16 7.699999e-05 17 6.629289e-05 18 6.036981e-05 19 5.854733e-05 20 5.307987e-05 21 4.806804e-05 22 4.328402e-05 23 4.168934e-05 24 3.713313e-05 25 3.394378e-05 26 3.280473e-05 27 3.166568e-05 29 2.597041e-05 30 2.574260e-05 28 2.528698e-05 31 2.232544e-05 33 2.186982e-05 34 2.004733e-05 32 1.959171e-05 35 1.457988e-05 36 1.412426e-05 37 1.298521e-05 40 1.070710e-05 39 1.047929e-05 38 1.025148e-05 41 8.656804e-06 42 8.201182e-06 43 7.745561e-06 44 5.923076e-06 46 4.784023e-06 45 4.100591e-06 47 4.100591e-06 50 3.872781e-06 48 3.644970e-06 52 3.417159e-06 51 3.189349e-06 53 2.961538e-06 49 2.961538e-06 UU 2.505917e-06 55 2.278106e-06 54 2.278106e-06 56 1.366864e-06 58 1.139053e-06 60 1.139053e-06 57 9.112425e-07 59 9.112425e-07 64 6.834319e-07 72 6.834319e-07 69 6.834319e-07 70 6.834319e-07 65 6.834319e-07 68 6.834319e-07 63 6.834319e-07 80 4.556212e-07 67 4.556212e-07 74 4.556212e-07 83 4.556212e-07 62 4.556212e-07 66 4.556212e-07 78 4.556212e-07 73 4.556212e-07 79 4.556212e-07 91 4.556212e-07 86 4.556212e-07 76 4.556212e-07 93 4.556212e-07 90 4.556212e-07 84 4.556212e-07 81 4.556212e-07 71 4.556212e-07 92 2.278106e-07 94 2.278106e-07 87 2.278106e-07 99 2.278106e-07 61 2.278106e-07 75 2.278106e-07 95 2.278106e-07 88 2.278106e-07 85 2.278106e-07 82 2.278106e-07 Name: P_ID, dtype: float64 ------------------- Cantidad de observaciones en: V_ID 01 5.307762e-01 02 3.667687e-01 03 5.088811e-02 99 3.739284e-02 04 1.002595e-02 05 2.186754e-03 06 7.112248e-04 07 3.107337e-04 08 1.729083e-04 09 1.248402e-04 UU 7.540531e-05 10 7.403845e-05 11 6.036981e-05 12 4.715680e-05 13 4.032248e-05 14 3.143787e-05 15 2.642603e-05 16 2.164201e-05 17 1.936390e-05 18 1.822485e-05 19 1.663018e-05 20 1.366864e-05 23 1.161834e-05 21 1.093491e-05 22 1.093491e-05 24 1.002367e-05 25 8.884614e-06 30 8.428993e-06 26 7.973372e-06 32 7.973372e-06 27 7.745561e-06 28 7.517750e-06 31 7.289940e-06 29 6.378697e-06 35 5.923076e-06 33 5.923076e-06 36 5.695265e-06 34 5.467455e-06 37 4.100591e-06 38 3.417159e-06 56 3.189349e-06 44 3.189349e-06 40 3.189349e-06 41 2.961538e-06 48 2.961538e-06 42 2.961538e-06 43 2.733727e-06 39 2.505917e-06 54 2.505917e-06 52 2.505917e-06 46 2.278106e-06 53 2.278106e-06 49 2.278106e-06 47 2.050296e-06 51 1.822485e-06 50 1.594674e-06 66 1.594674e-06 45 1.366864e-06 72 1.366864e-06 59 1.139053e-06 63 1.139053e-06 55 1.139053e-06 60 1.139053e-06 68 9.112425e-07 61 9.112425e-07 70 9.112425e-07 71 9.112425e-07 64 9.112425e-07 57 9.112425e-07 67 9.112425e-07 62 6.834319e-07 69 6.834319e-07 76 6.834319e-07 58 4.556212e-07 65 4.556212e-07 86 4.556212e-07 77 2.278106e-07 73 2.278106e-07 74 2.278106e-07 85 2.278106e-07 75 2.278106e-07 Name: V_ID, dtype: float64 ------------------- Cantidad de observaciones en: V_YEAR 2000 5.518097e-02 UUUU 5.499417e-02 1998 5.034250e-02 2002 5.015000e-02 1999 4.910503e-02 2003 4.773703e-02 2001 4.761265e-02 1997 4.480215e-02 NNNN 4.439482e-02 2005 3.881004e-02 1995 3.850341e-02 2004 3.850204e-02 1996 3.391690e-02 1994 3.327539e-02 1992 3.275416e-02 2006 3.271452e-02 1993 3.183722e-02 2007 3.134424e-02 1991 2.876200e-02 1990 2.721858e-02 2008 2.511885e-02 1989 2.382352e-02 1988 2.077975e-02 2009 1.801526e-02 2010 1.565651e-02 1987 1.419625e-02 1986 1.190652e-02 2011 1.096521e-02 2012 8.698948e-03 1985 7.904117e-03 2013 5.988686e-03 1984 5.541949e-03 1983 3.257464e-03 1981 2.966778e-03 2014 2.450331e-03 1982 2.375609e-03 1980 2.018630e-03 1979 1.476896e-03 1978 1.026970e-03 1977 7.829851e-04 1976 4.900206e-04 1975 3.697366e-04 1974 2.756508e-04 1973 2.594763e-04 1972 2.371509e-04 2015 2.102692e-04 1970 1.626568e-04 1969 1.594674e-04 1971 1.437485e-04 1968 1.316745e-04 1967 1.139053e-04 1966 8.360650e-05 1965 7.130472e-05 1964 4.396745e-05 1963 3.280473e-05 1962 2.756508e-05 1960 2.255325e-05 1957 1.890828e-05 1939 1.571893e-05 1956 1.549112e-05 1959 1.435207e-05 1958 1.435207e-05 1961 1.321302e-05 1955 1.139053e-05 1952 8.656804e-06 1950 8.201182e-06 1947 7.289940e-06 1949 6.378697e-06 1930 6.150887e-06 1953 5.923076e-06 1920 5.923076e-06 1954 5.695265e-06 1951 5.467455e-06 1938 5.467455e-06 1948 5.011834e-06 1946 4.784023e-06 1915 4.556212e-06 1931 4.328402e-06 1926 4.100591e-06 1928 4.100591e-06 1940 3.872781e-06 1937 2.961538e-06 1944 2.733727e-06 1945 2.733727e-06 1922 2.733727e-06 1935 2.733727e-06 1901 2.733727e-06 1929 2.505917e-06 1923 2.505917e-06 1914 2.505917e-06 1941 2.278106e-06 1925 2.278106e-06 1919 2.278106e-06 1932 2.050296e-06 1933 2.050296e-06 1918 2.050296e-06 1911 1.822485e-06 1942 1.822485e-06 1903 1.594674e-06 1912 1.594674e-06 1927 1.594674e-06 1916 1.366864e-06 1921 1.366864e-06 1934 1.139053e-06 1908 1.139053e-06 1917 9.112425e-07 1913 9.112425e-07 1943 6.834319e-07 1924 6.834319e-07 1936 6.834319e-07 1905 4.556212e-07 1907 4.556212e-07 1906 2.278106e-07 1909 2.278106e-07 1910 2.278106e-07 Name: V_YEAR, dtype: float64 ------------------- Cantidad de observaciones en: P_AGE UU 0.064159 18 0.029324 19 0.028557 20 0.027030 17 0.026959 21 0.025247 22 0.023611 23 0.022318 24 0.020875 25 0.020186 26 0.018817 27 0.018021 28 0.017413 30 0.016931 29 0.016796 40 0.016631 16 0.016494 42 0.016298 35 0.016191 41 0.016098 38 0.016076 39 0.016037 31 0.016017 43 0.015997 32 0.015932 37 0.015927 33 0.015839 36 0.015836 45 0.015835 44 0.015816 34 0.015758 46 0.015266 47 0.014804 48 0.014604 49 0.014193 50 0.014000 51 0.013220 52 0.012829 53 0.012317 54 0.011610 55 0.011089 56 0.010353 57 0.009759 58 0.009216 15 0.008998 59 0.008700 60 0.008340 61 0.007488 62 0.007064 14 0.006979 01 0.006738 63 0.006706 64 0.006263 65 0.006026 13 0.005480 66 0.005372 12 0.005203 67 0.005139 10 0.004896 11 0.004814 68 0.004795 09 0.004697 08 0.004619 07 0.004574 05 0.004552 69 0.004514 70 0.004499 04 0.004491 06 0.004455 03 0.004349 02 0.004333 71 0.004117 72 0.004048 73 0.003758 74 0.003672 75 0.003520 76 0.003345 77 0.003105 NN 0.003069 78 0.002911 79 0.002756 80 0.002597 81 0.002148 82 0.001969 83 0.001751 84 0.001459 85 0.001258 86 0.001043 87 0.000819 88 0.000630 89 0.000478 90 0.000380 91 0.000241 92 0.000174 93 0.000118 94 0.000075 99 0.000054 95 0.000049 96 0.000033 98 0.000031 97 0.000019 Name: P_AGE, dtype: float64 -------------------
Descripción: No veo datos atipicos como valores negativos, asignaciones de valores no detallados en el diccionario de datos, etc.
El siguiente paso es realizar graficos de conteo analizar las distribuciones de las variables
plt.rcParams["figure.figsize"] = (16,6)
for i in numerical_vars:
sns.countplot(x=i, data=data)
plt.xticks(rotation=90)
plt.show();
En todas las variables salvo en 'P_AGE' y 'V_YEAR', los valores 'N' son minoritarios. Contrariamente en estas dos restantes, los valores tipo 'U' son los más observados.
Vamos a revisar la distribución de la variable objetivo de los valores tipo 'U' y tipo 'N' por separado. El objetivo es corroborar si la falta de información nos puede ayudar a discriminar a las personas fallecidas del resto.
unknown = ['U', 'UU', 'UUU', 'UUUU']
for i in numerical_vars:
print('')
print('Variable:', i)
print('')
print(f'Los valores desconocidos representan el {np.round(data[i].isin(unknown).sum()*100/len((data[i].isna())),2)}% de los datos para esta variable')
print('')
if len(data[data[i].isin(unknown)]) == 0:
print('La variable no cuenta con observaiones nulas')
else:
print('Cuando la variable es desconocida, la distribución de la variable objetivo es:')
print(np.round(data[(data[i].isin(unknown))]['C_SEV'].value_counts()*100/len(data[(data[i].isin(unknown))]),4))
proporcion_fallecidos = pd.DataFrame(data['C_SEV'].value_counts()/len(data))
proporcion_fallecidos.columns= ['Target']
proporcion_fallecidos['Missing'] = data[data[i].isin(unknown)]['C_SEV'].value_counts()/len(data[data[i].isin(unknown)])
proporcion_fallecidos['Difference'] = proporcion_fallecidos['Missing'] - proporcion_fallecidos.Target
result = np.round(proporcion_fallecidos.iloc[1].Difference*100/proporcion_fallecidos.iloc[1].Target, 2)
print('')
if result < 0:
print(f'Al ser desconocida la categoría {i}, la probabilidad de ser un accidente fatal disminuye un {np.abs(result)}% con respecto a la distribución de las fatalidades')
elif result > 0:
print(f'Al ser desconocida la categoría {i}, la probabilidad de ser un accidente fatal aumenta un {result}% con respecto a la distribución de las fatalidades')
elif result == np.nan:
pass
print('')
print('La cantidad de observaciones desconocidas es:', len(data[data[i].isin(unknown)]))
print('La cantidad de observaciones no desconocidas es:', len(data[~data[i].isin(unknown)]))
print('------------------------------------------------------------------------------------------')
Variable: C_YEAR Los valores desconocidos representan el 0.0% de los datos para esta variable La variable no cuenta con observaiones nulas ------------------------------------------------------------------------------------------ Variable: C_MNTH Los valores desconocidos representan el 0.01% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 98.6395 1 1.3605 Name: C_SEV, dtype: float64 Al ser desconocida la categoría C_MNTH, la probabilidad de ser un accidente fatal disminuye un 19.25% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 294 La cantidad de observaciones no desconocidas es: 4389317 ------------------------------------------------------------------------------------------ Variable: C_WDAY Los valores desconocidos representan el 0.02% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 99.0982 1 0.9018 Name: C_SEV, dtype: float64 Al ser desconocida la categoría C_WDAY, la probabilidad de ser un accidente fatal disminuye un 46.48% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 998 La cantidad de observaciones no desconocidas es: 4388613 ------------------------------------------------------------------------------------------ Variable: C_HOUR Los valores desconocidos representan el 1.01% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 98.1766 1 1.8234 Name: C_SEV, dtype: float64 Al ser desconocida la categoría C_HOUR, la probabilidad de ser un accidente fatal aumenta un 8.22% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 44423 La cantidad de observaciones no desconocidas es: 4345188 ------------------------------------------------------------------------------------------ Variable: P_ID Los valores desconocidos representan el 0.0% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 90.9091 1 9.0909 Name: C_SEV, dtype: float64 Al ser desconocida la categoría P_ID, la probabilidad de ser un accidente fatal aumenta un 439.56% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 11 La cantidad de observaciones no desconocidas es: 4389600 ------------------------------------------------------------------------------------------ Variable: V_ID Los valores desconocidos representan el 0.01% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 93.0514 1 6.9486 Name: C_SEV, dtype: float64 Al ser desconocida la categoría V_ID, la probabilidad de ser un accidente fatal aumenta un 312.41% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 331 La cantidad de observaciones no desconocidas es: 4389280 ------------------------------------------------------------------------------------------ Variable: V_YEAR Los valores desconocidos representan el 5.5% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 98.4242 1 1.5758 Name: C_SEV, dtype: float64 Al ser desconocida la categoría V_YEAR, la probabilidad de ser un accidente fatal disminuye un 6.48% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 241403 La cantidad de observaciones no desconocidas es: 4148208 ------------------------------------------------------------------------------------------ Variable: P_AGE Los valores desconocidos representan el 6.42% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 98.9941 1 1.0059 Name: C_SEV, dtype: float64 Al ser desconocida la categoría P_AGE, la probabilidad de ser un accidente fatal disminuye un 40.3% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 281635 La cantidad de observaciones no desconocidas es: 4107976 ------------------------------------------------------------------------------------------
Como mencionamos anteriormente, solo consideraremos los casos de 'V_YEAR' y 'P_AGE', dado que son realmente bajas las observaciones nulas, y los desvíos de la distribución de la variable objetivo en estos casos se pueden deber a anomalías por tener tan pocos datos. A estas variables se considerará imputarlas o no considerarlas más adelante.
Caso 'V_YEAR': Se observan muchos datos pero la distribución es muy similar a la observada en el dataset. También será analizada más adelante junto con las demás variables.
Caso 'P_AGE': Se observan muchos datos y la distribución es muy diferente a la observada en el dataset. Con lo cual, generaremos una categoría adicional llamada 'NA' en dicha columna.
Ahora realizaremos el mismo análisis pero para los datos tipo 'N':
unknown = ['N', 'NN', 'NNN', 'NNNN']
for i in numerical_vars:
print('')
print('Variable:', i)
print('')
print(f'Los valores nulos representan el {np.round(data[i].isin(unknown).sum()*100/len((data[i].isna())),2)}% de los datos para esta variable')
print('')
if len(data[data[i].isin(unknown)]) == 0:
print('La variable no cuenta con observaiones nulas')
else:
print('Cuando la variable es nula, la distribución de la variable objetivo es:')
print(np.round(data[(data[i].isin(unknown))]['C_SEV'].value_counts()*100/len(data[(data[i].isin(unknown))]),4))
proporcion_fallecidos = pd.DataFrame(data['C_SEV'].value_counts()/len(data))
proporcion_fallecidos.columns= ['Target']
proporcion_fallecidos['Missing'] = data[data[i].isin(unknown)]['C_SEV'].value_counts()/len(data[data[i].isin(unknown)])
proporcion_fallecidos['Difference'] = proporcion_fallecidos['Missing'] - proporcion_fallecidos.Target
result = np.round(proporcion_fallecidos.iloc[1].Difference*100/proporcion_fallecidos.iloc[1].Target, 2)
print('')
if result < 0:
print(f'Al ser NA la categoría {i}, la probabilidad de ser un accidente fatal disminuye un {np.abs(result)}% con respecto a la distribución de las fatalidades')
elif result > 0:
print(f'Al ser NA la categoría {i}, la probabilidad de ser un accidente fatal aumenta un {result}% con respecto a la distribución de las fatalidades')
elif result == np.nan:
pass
print('')
print('La cantidad de observaciones nulas es:', len(data[data[i].isin(unknown)]))
print('La cantidad de observaciones no nulas es:', len(data[~data[i].isin(unknown)]))
print('------------------------------------------------------------------------------------------')
Variable: C_YEAR Los valores nulos representan el 0.0% de los datos para esta variable La variable no cuenta con observaiones nulas ------------------------------------------------------------------------------------------ Variable: C_MNTH Los valores nulos representan el 0.0% de los datos para esta variable La variable no cuenta con observaiones nulas ------------------------------------------------------------------------------------------ Variable: C_WDAY Los valores nulos representan el 0.0% de los datos para esta variable La variable no cuenta con observaiones nulas ------------------------------------------------------------------------------------------ Variable: C_HOUR Los valores nulos representan el 0.0% de los datos para esta variable La variable no cuenta con observaiones nulas ------------------------------------------------------------------------------------------ Variable: P_ID Los valores nulos representan el 0.19% de los datos para esta variable Cuando la variable es nula, la distribución de la variable objetivo es: 0 98.1531 1 1.8469 Name: C_SEV, dtype: float64 Al ser NA la categoría P_ID, la probabilidad de ser un accidente fatal aumenta un 9.62% con respecto a la distribución de las fatalidades La cantidad de observaciones nulas es: 8230 La cantidad de observaciones no nulas es: 4381381 ------------------------------------------------------------------------------------------ Variable: V_ID Los valores nulos representan el 0.0% de los datos para esta variable La variable no cuenta con observaiones nulas ------------------------------------------------------------------------------------------ Variable: V_YEAR Los valores nulos representan el 4.44% de los datos para esta variable Cuando la variable es nula, la distribución de la variable objetivo es: 0 97.4019 1 2.5981 Name: C_SEV, dtype: float64 Al ser NA la categoría V_YEAR, la probabilidad de ser un accidente fatal aumenta un 54.2% con respecto a la distribución de las fatalidades La cantidad de observaciones nulas es: 194876 La cantidad de observaciones no nulas es: 4194735 ------------------------------------------------------------------------------------------ Variable: P_AGE Los valores nulos representan el 0.31% de los datos para esta variable Cuando la variable es nula, la distribución de la variable objetivo es: 0 98.1444 1 1.8556 Name: C_SEV, dtype: float64 Al ser NA la categoría P_AGE, la probabilidad de ser un accidente fatal aumenta un 10.13% con respecto a la distribución de las fatalidades La cantidad de observaciones nulas es: 13473 La cantidad de observaciones no nulas es: 4376138 ------------------------------------------------------------------------------------------
Igual que antes, solo consideraremos los casos de 'V_YEAR' y 'P_AGE', dado que son realmente bajas las observaciones nulas, y los desvíos de la distribución de la variable objetivo en estos casos se pueden deber a anomalías por tener tan pocos datos. A estas variables se considerará imputarlas o no considerarlas más adelante.
Caso 'V_YEAR': Se observan muchos datos y la distribución es muy diferente a la observada en el dataset. Con lo cual, generaremos una categoría adicional llamada 'NA' en dicha columna.
Caso 'P_AGE': Se observan pocos datos, a este tipo de datos los trataremos junto con los demás.
Generaré variables dummies ya que al transformar a estas variables a numéricas, tanto las observaciones N comos las U se tranformarán en NA y no tienen el mismo tratamiento dada la diferencia en las distribuciones de la variable objetivo en cada caso particular
unknown = ['N', 'NN', 'NNN', 'NNNN', 'U', 'UU', 'UUU', 'UUUU']
for i in numerical_vars:
for j in unknown:
data[i + '_' + j] = np.where(data[i] == j, 1, 0)
for i in numerical_vars:
data[i] = pd.to_numeric(data[i], errors='coerce', downcast='integer')
data.shape
(4389611, 83)
data = data.loc[:, (data != 0).any(axis=0)]
data.shape
(4389611, 29)
data.isnull().sum()
C_YEAR 0 C_MNTH 294 C_WDAY 998 C_HOUR 44423 C_VEHS 0 C_CONF 0 C_RCFG 0 C_WTHR 0 C_RSUR 0 V_ID 331 V_TYPE 0 V_YEAR 436279 P_ID 8241 P_SEX 0 P_AGE 295108 P_PSN 0 P_SAFE 0 P_USER 0 C_SEV 0 C_MNTH_UU 0 C_WDAY_U 0 C_HOUR_UU 0 P_ID_NN 0 P_ID_UU 0 V_ID_UU 0 V_YEAR_NNNN 0 V_YEAR_UUUU 0 P_AGE_NN 0 P_AGE_UU 0 dtype: int64
data.head()
| C_YEAR | C_MNTH | C_WDAY | C_HOUR | C_VEHS | C_CONF | C_RCFG | C_WTHR | C_RSUR | V_ID | ... | C_MNTH_UU | C_WDAY_U | C_HOUR_UU | P_ID_NN | P_ID_UU | V_ID_UU | V_YEAR_NNNN | V_YEAR_UUUU | P_AGE_NN | P_AGE_UU | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 4850824 | 2011 | 10.0 | 4.0 | 7.0 | 03 | 06 | 01 | 3 | 2 | 1.0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 3179371 | 2006 | 11.0 | 4.0 | 9.0 | 02 | 35 | UU | 1 | Q | 2.0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 5330174 | 2013 | 4.0 | 5.0 | 15.0 | 02 | 21 | 01 | 1 | 1 | 1.0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 4880251 | 2011 | 11.0 | 4.0 | 18.0 | 02 | 21 | 01 | 1 | 1 | 1.0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 3039624 | 2006 | 7.0 | 4.0 | 13.0 | 02 | 21 | 02 | 1 | 1 | 1.0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 rows × 29 columns
categorical_vals = [c for c in data if c not in numerical_vars][1:10]
categorical_vals
['C_CONF', 'C_RCFG', 'C_WTHR', 'C_RSUR', 'V_TYPE', 'P_SEX', 'P_PSN', 'P_SAFE', 'P_USER']
for i in categorical_vals:
print(f'Cantidad de observaciones en: {str(data[[i]].columns.tolist()[0])}')
print('')
print(data[i].value_counts()/len(data))
#buscar que cuando haya algun U en el string, cuente en valores absolutos y relativos cuantos hay
print('')
print('-------------------')
Cantidad de observaciones en: C_CONF 21 0.302363 35 0.148179 06 0.087994 36 0.073466 33 0.072123 QQ 0.048653 04 0.036587 22 0.033649 31 0.033290 02 0.031835 UU 0.030457 03 0.028202 01 0.015745 41 0.013855 23 0.011969 34 0.010562 24 0.008895 32 0.008095 05 0.002217 25 0.001864 Name: C_CONF, dtype: float64 ------------------- Cantidad de observaciones en: C_RCFG 02 0.468577 01 0.354826 UU 0.086217 03 0.049310 QQ 0.024685 05 0.008734 04 0.004058 08 0.002009 06 0.001027 09 0.000288 07 0.000177 10 0.000095 Name: C_RCFG, dtype: float64 ------------------- Cantidad de observaciones en: C_WTHR 1 0.695170 3 0.102447 2 0.102359 4 0.060548 U 0.015019 6 0.014113 5 0.005181 7 0.002604 Q 0.002561 Name: C_WTHR, dtype: float64 ------------------- Cantidad de observaciones en: C_RSUR 1 0.656121 2 0.184489 5 0.054715 3 0.044242 Q 0.029103 U 0.013410 4 0.012311 6 0.004322 7 0.001035 8 0.000202 9 0.000050 Name: C_RSUR, dtype: float64 ------------------- Cantidad de observaciones en: V_TYPE 01 0.823851 NN 0.038846 06 0.030018 14 0.020962 17 0.020885 07 0.014992 08 0.012035 05 0.011269 11 0.008722 UU 0.005076 QQ 0.004346 09 0.003568 16 0.001646 20 0.001294 22 0.000786 18 0.000536 23 0.000529 19 0.000347 10 0.000152 21 0.000139 Name: V_TYPE, dtype: float64 ------------------- Cantidad de observaciones en: P_SEX M 0.541057 F 0.416477 U 0.039948 N 0.002518 Name: P_SEX, dtype: float64 ------------------- Cantidad de observaciones en: P_PSN 11 0.669690 13 0.151021 23 0.044106 21 0.036952 99 0.035605 22 0.015397 12 0.014976 UU 0.009849 96 0.007491 32 0.005135 QQ 0.004449 NN 0.002402 98 0.001141 33 0.000973 31 0.000783 97 0.000031 Name: P_PSN, dtype: float64 ------------------- Cantidad de observaciones en: P_SAFE 02 0.710891 UU 0.104727 NN 0.097553 01 0.033871 13 0.025343 09 0.016436 QQ 0.008037 12 0.003123 10 0.000018 11 0.000002 Name: P_SAFE, dtype: float64 ------------------- Cantidad de observaciones en: P_USER 1 0.624188 2 0.266594 3 0.037393 U 0.029979 5 0.020962 4 0.020885 Name: P_USER, dtype: float64 -------------------
Verificamos que los datos concuerdan con los valores esperados
Vamos a revisar la distribución de la variable objetivo de los valores tipo 'U' y tipo 'N' por separado. El objetivo es corroborar si la falta de información nos puede ayudar a discriminar a las personas fallecidas del resto.
unknown = ['N', 'NN', 'NNN', 'NNNN']
for i in categorical_vals:
print('')
print('Variable:', i)
print('')
print(f'Los valores nulos representan el {np.round(data[i].isin(unknown).sum()*100/len((data[i].isna())),2)}% de los datos para esta variable')
print('')
if len(data[data[i].isin(unknown)]) == 0:
print('La variable no cuenta con observaiones nulas')
else:
print('Cuando la variable es nula, la distribución de la variable objetivo es:')
print(np.round(data[(data[i].isin(unknown))]['C_SEV'].value_counts()*100/len(data[(data[i].isin(unknown))]),4))
proporcion_fallecidos = pd.DataFrame(data['C_SEV'].value_counts()/len(data))
proporcion_fallecidos.columns= ['Target']
proporcion_fallecidos['Missing'] = data[data[i].isin(unknown)]['C_SEV'].value_counts()/len(data[data[i].isin(unknown)])
proporcion_fallecidos['Difference'] = proporcion_fallecidos['Missing'] - proporcion_fallecidos.Target
result = np.round(proporcion_fallecidos.iloc[1].Difference*100/proporcion_fallecidos.iloc[1].Target, 2)
print('')
if result < 0:
print(f'Al ser NA la categoría {i}, la probabilidad de ser un accidente fatal disminuye un {np.abs(result)}% con respecto a la distribución de las fatalidades')
elif result > 0:
print(f'Al ser NA la categoría {i}, la probabilidad de ser un accidente fatal aumenta un {result}% con respecto a la distribución de las fatalidades')
elif result == np.nan:
pass
print('')
print('La cantidad de observaciones nulas es:', len(data[data[i].isin(unknown)]))
print('La cantidad de observaciones no nulas es:', len(data[~data[i].isin(unknown)]))
print('------------------------------------------------------------------------------------------')
Variable: C_CONF Los valores nulos representan el 0.0% de los datos para esta variable La variable no cuenta con observaiones nulas ------------------------------------------------------------------------------------------ Variable: C_RCFG Los valores nulos representan el 0.0% de los datos para esta variable La variable no cuenta con observaiones nulas ------------------------------------------------------------------------------------------ Variable: C_WTHR Los valores nulos representan el 0.0% de los datos para esta variable La variable no cuenta con observaiones nulas ------------------------------------------------------------------------------------------ Variable: C_RSUR Los valores nulos representan el 0.0% de los datos para esta variable La variable no cuenta con observaiones nulas ------------------------------------------------------------------------------------------ Variable: V_TYPE Los valores nulos representan el 3.88% de los datos para esta variable Cuando la variable es nula, la distribución de la variable objetivo es: 0 97.1306 1 2.8694 Name: C_SEV, dtype: float64 Al ser NA la categoría V_TYPE, la probabilidad de ser un accidente fatal aumenta un 70.3% con respecto a la distribución de las fatalidades La cantidad de observaciones nulas es: 170521 La cantidad de observaciones no nulas es: 4219090 ------------------------------------------------------------------------------------------ Variable: P_SEX Los valores nulos representan el 0.25% de los datos para esta variable Cuando la variable es nula, la distribución de la variable objetivo es: 0 97.9826 1 2.0174 Name: C_SEV, dtype: float64 Al ser NA la categoría P_SEX, la probabilidad de ser un accidente fatal aumenta un 19.73% con respecto a la distribución de las fatalidades La cantidad de observaciones nulas es: 11054 La cantidad de observaciones no nulas es: 4378557 ------------------------------------------------------------------------------------------ Variable: P_PSN Los valores nulos representan el 0.24% de los datos para esta variable Cuando la variable es nula, la distribución de la variable objetivo es: 0 97.8284 1 2.1716 Name: C_SEV, dtype: float64 Al ser NA la categoría P_PSN, la probabilidad de ser un accidente fatal aumenta un 28.89% con respecto a la distribución de las fatalidades La cantidad de observaciones nulas es: 10545 La cantidad de observaciones no nulas es: 4379066 ------------------------------------------------------------------------------------------ Variable: P_SAFE Los valores nulos representan el 9.76% de los datos para esta variable Cuando la variable es nula, la distribución de la variable objetivo es: 0 98.5741 1 1.4259 Name: C_SEV, dtype: float64 Al ser NA la categoría P_SAFE, la probabilidad de ser un accidente fatal disminuye un 15.37% con respecto a la distribución de las fatalidades La cantidad de observaciones nulas es: 428218 La cantidad de observaciones no nulas es: 3961393 ------------------------------------------------------------------------------------------ Variable: P_USER Los valores nulos representan el 0.0% de los datos para esta variable La variable no cuenta con observaiones nulas ------------------------------------------------------------------------------------------
Solo consideraremos los casos de 'V_TYPE' y 'P_SAFE', dado que son realmente bajas las observaciones nulas para el resto de las variables. Estos desvíos de la distribución de la variable objetivo en estos casos se pueden deber a anomalías por tener tan pocos datos. A estas variables se considerará imputarlas o no considerarlas más adelante.
Caso 'V_TYPE': Se observan muchos datos y la distribución es muy diferente a la observada en el dataset. Con lo cual, generaremos una categoría adicional llamada 'NA' en dicha columna.
Caso 'P_SAFE': Se observan muchos datos y la distribución es muy diferente a la observada en el dataset. Con lo cual, generaremos una categoría adicional llamada 'NA' en dicha columna.
Ahora realizaremos el mismo análisis pero para los datos tipo 'U':
unknown = ['U', 'UU', 'UUU', 'UUUU']
for i in categorical_vals:
print('')
print('Variable:', i)
print('')
print(f'Los valores desconocidos representan el {np.round(data[i].isin(unknown).sum()*100/len((data[i].isna())),2)}% de los datos para esta variable')
print('')
if len(data[data[i].isin(unknown)]) == 0:
print('La variable no cuenta con observaiones nulas')
else:
print('Cuando la variable es desconocida, la distribución de la variable objetivo es:')
print(np.round(data[(data[i].isin(unknown))]['C_SEV'].value_counts()*100/len(data[(data[i].isin(unknown))]),4))
proporcion_fallecidos = pd.DataFrame(data['C_SEV'].value_counts()/len(data))
proporcion_fallecidos.columns= ['Target']
proporcion_fallecidos['Missing'] = data[data[i].isin(unknown)]['C_SEV'].value_counts()/len(data[data[i].isin(unknown)])
proporcion_fallecidos['Difference'] = proporcion_fallecidos['Missing'] - proporcion_fallecidos.Target
result = np.round(proporcion_fallecidos.iloc[1].Difference*100/proporcion_fallecidos.iloc[1].Target, 2)
print('')
if result < 0:
print(f'Al ser desconocida la categoría {i}, la probabilidad de ser un accidente fatal disminuye un {np.abs(result)}% con respecto a la distribución de las fatalidades')
elif result > 0:
print(f'Al ser desconocida la categoría {i}, la probabilidad de ser un accidente fatal aumenta un {result}% con respecto a la distribución de las fatalidades')
elif result == np.nan:
pass
print('')
print('La cantidad de observaciones desconocidas es:', len(data[data[i].isin(unknown)]))
print('La cantidad de observaciones no desconocidas es:', len(data[~data[i].isin(unknown)]))
print('------------------------------------------------------------------------------------------')
Variable: C_CONF Los valores desconocidos representan el 3.05% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 98.5833 1 1.4167 Name: C_SEV, dtype: float64 Al ser desconocida la categoría C_CONF, la probabilidad de ser un accidente fatal disminuye un 15.92% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 133693 La cantidad de observaciones no desconocidas es: 4255918 ------------------------------------------------------------------------------------------ Variable: C_RCFG Los valores desconocidos representan el 8.62% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 98.8155 1 1.1845 Name: C_SEV, dtype: float64 Al ser desconocida la categoría C_RCFG, la probabilidad de ser un accidente fatal disminuye un 29.7% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 378457 La cantidad de observaciones no desconocidas es: 4011154 ------------------------------------------------------------------------------------------ Variable: C_WTHR Los valores desconocidos representan el 1.5% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 99.1233 1 0.8767 Name: C_SEV, dtype: float64 Al ser desconocida la categoría C_WTHR, la probabilidad de ser un accidente fatal disminuye un 47.97% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 65928 La cantidad de observaciones no desconocidas es: 4323683 ------------------------------------------------------------------------------------------ Variable: C_RSUR Los valores desconocidos representan el 1.34% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 98.9586 1 1.0414 Name: C_SEV, dtype: float64 Al ser desconocida la categoría C_RSUR, la probabilidad de ser un accidente fatal disminuye un 38.19% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 58863 La cantidad de observaciones no desconocidas es: 4330748 ------------------------------------------------------------------------------------------ Variable: V_TYPE Los valores desconocidos representan el 0.51% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 98.8018 1 1.1982 Name: C_SEV, dtype: float64 Al ser desconocida la categoría V_TYPE, la probabilidad de ser un accidente fatal disminuye un 28.88% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 22283 La cantidad de observaciones no desconocidas es: 4367328 ------------------------------------------------------------------------------------------ Variable: P_SEX Los valores desconocidos representan el 3.99% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 98.8754 1 1.1246 Name: C_SEV, dtype: float64 Al ser desconocida la categoría P_SEX, la probabilidad de ser un accidente fatal disminuye un 33.25% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 175354 La cantidad de observaciones no desconocidas es: 4214257 ------------------------------------------------------------------------------------------ Variable: P_PSN Los valores desconocidos representan el 0.98% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 97.8349 1 2.1651 Name: C_SEV, dtype: float64 Al ser desconocida la categoría P_PSN, la probabilidad de ser un accidente fatal aumenta un 28.5% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 43232 La cantidad de observaciones no desconocidas es: 4346379 ------------------------------------------------------------------------------------------ Variable: P_SAFE Los valores desconocidos representan el 10.47% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 98.0044 1 1.9956 Name: C_SEV, dtype: float64 Al ser desconocida la categoría P_SAFE, la probabilidad de ser un accidente fatal aumenta un 18.44% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 459711 La cantidad de observaciones no desconocidas es: 3929900 ------------------------------------------------------------------------------------------ Variable: P_USER Los valores desconocidos representan el 3.0% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 97.4954 1 2.5046 Name: C_SEV, dtype: float64 Al ser desconocida la categoría P_USER, la probabilidad de ser un accidente fatal aumenta un 48.65% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 131596 La cantidad de observaciones no desconocidas es: 4258015 ------------------------------------------------------------------------------------------
Las variables que tendrán como una categoría 'NA' aceptada para el tratamiento de encoding de estas variables categóricas son:
Las variables que serán imputadas las observaciones serán:
Ahora realizaremos el mismo análisis pero para los datos tipo 'Q', es necesario detallar que no se tratan de variables tipo NA sino que estamos hablando de observaciones tipo 'otros':
unknown = ['Q','QQ','QQQ','QQQQ']
for i in categorical_vals:
print('')
print('Variable:', i)
print('')
print(f'Los valores desconocidos representan el {np.round(data[i].isin(unknown).sum()*100/len((data[i].isna())),2)}% de los datos para esta variable')
print('')
if len(data[data[i].isin(unknown)]) == 0:
print('La variable no cuenta con observaciones desconocida')
else:
print('Cuando la variable es desconocida, la distribución de la variable objetivo es:')
print(np.round(data[(data[i].isin(unknown))]['C_SEV'].value_counts()*100/len(data[(data[i].isin(unknown))]),4))
proporcion_fallecidos = pd.DataFrame(data['C_SEV'].value_counts()/len(data))
proporcion_fallecidos.columns= ['Target']
proporcion_fallecidos['Missing'] = data[data[i].isin(unknown)]['C_SEV'].value_counts()/len(data[data[i].isin(unknown)])
proporcion_fallecidos['Difference'] = proporcion_fallecidos['Missing'] - proporcion_fallecidos.Target
result = np.round(proporcion_fallecidos.iloc[1].Difference*100/proporcion_fallecidos.iloc[1].Target, 2)
print('')
if result < 0:
print(f'Al ser desconocida la categoría {i}, la probabilidad de ser un accidente fatal disminuye un {np.abs(result)}% con respecto a la distribución de las fatalidades')
elif result > 0:
print(f'Al ser desconocida la categoría {i}, la probabilidad de ser un accidente fatal aumenta un {result}% con respecto a la distribución de las fatalidades')
elif result == np.nan:
pass
print('')
print('La cantidad de observaciones desconocidas es:', len(data[data[i].isin(unknown)]))
print('La cantidad de observaciones no desconocidas es:', len(data[~data[i].isin(unknown)]))
print('------------------------------------------------------------------------------------------')
Variable: C_CONF Los valores desconocidos representan el 4.87% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 98.1317 1 1.8683 Name: C_SEV, dtype: float64 Al ser desconocida la categoría C_CONF, la probabilidad de ser un accidente fatal aumenta un 10.88% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 213567 La cantidad de observaciones no desconocidas es: 4176044 ------------------------------------------------------------------------------------------ Variable: C_RCFG Los valores desconocidos representan el 2.47% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 97.8875 1 2.1125 Name: C_SEV, dtype: float64 Al ser desconocida la categoría C_RCFG, la probabilidad de ser un accidente fatal aumenta un 25.38% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 108356 La cantidad de observaciones no desconocidas es: 4281255 ------------------------------------------------------------------------------------------ Variable: C_WTHR Los valores desconocidos representan el 0.26% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 98.3096 1 1.6904 Name: C_SEV, dtype: float64 Al ser desconocida la categoría C_WTHR, la probabilidad de ser un accidente fatal aumenta un 0.33% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 11240 La cantidad de observaciones no desconocidas es: 4378371 ------------------------------------------------------------------------------------------ Variable: C_RSUR Los valores desconocidos representan el 2.91% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 98.0462 1 1.9538 Name: C_SEV, dtype: float64 Al ser desconocida la categoría C_RSUR, la probabilidad de ser un accidente fatal aumenta un 15.96% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 127751 La cantidad de observaciones no desconocidas es: 4261860 ------------------------------------------------------------------------------------------ Variable: V_TYPE Los valores desconocidos representan el 0.43% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 97.5366 1 2.4634 Name: C_SEV, dtype: float64 Al ser desconocida la categoría V_TYPE, la probabilidad de ser un accidente fatal aumenta un 46.21% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 19079 La cantidad de observaciones no desconocidas es: 4370532 ------------------------------------------------------------------------------------------ Variable: P_SEX Los valores desconocidos representan el 0.0% de los datos para esta variable La variable no cuenta con observaciones desconocida ------------------------------------------------------------------------------------------ Variable: P_PSN Los valores desconocidos representan el 0.44% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 97.1788 1 2.8212 Name: C_SEV, dtype: float64 Al ser desconocida la categoría P_PSN, la probabilidad de ser un accidente fatal aumenta un 67.44% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 19531 La cantidad de observaciones no desconocidas es: 4370080 ------------------------------------------------------------------------------------------ Variable: P_SAFE Los valores desconocidos representan el 0.8% de los datos para esta variable Cuando la variable es desconocida, la distribución de la variable objetivo es: 0 97.1825 1 2.8175 Name: C_SEV, dtype: float64 Al ser desconocida la categoría P_SAFE, la probabilidad de ser un accidente fatal aumenta un 67.22% con respecto a la distribución de las fatalidades La cantidad de observaciones desconocidas es: 35279 La cantidad de observaciones no desconocidas es: 4354332 ------------------------------------------------------------------------------------------ Variable: P_USER Los valores desconocidos representan el 0.0% de los datos para esta variable La variable no cuenta con observaciones desconocida ------------------------------------------------------------------------------------------
En este punto, la idea es tranformar a las variables categóricas de forma tal, que podremos realizar diferentes encodings propuestos (OneHotEncoding si la variable es binaria o TargetEncoding si la variable es multiclase), o revisar posible existencias de valores outliers y así filtrarlos.
data['V_TYPE'].value_counts()/len(data)
01 0.823851 NN 0.038846 06 0.030018 14 0.020962 17 0.020885 07 0.014992 08 0.012035 05 0.011269 11 0.008722 UU 0.005076 QQ 0.004346 09 0.003568 16 0.001646 20 0.001294 22 0.000786 18 0.000536 23 0.000529 19 0.000347 10 0.000152 21 0.000139 Name: V_TYPE, dtype: float64
data['V_TYPE'] = np.where(data['V_TYPE'].isin(['05', '06', '07', '08', '18', '19', '20', '21']), 'truck', data['V_TYPE'])
data['V_TYPE'] = np.where(data['V_TYPE'].isin(['09', '10', '11']), 'bus', data['V_TYPE'])
data['V_TYPE'] = np.where(data['V_TYPE'].isin(['14', '16', '17', '22']), 'bike', data['V_TYPE'])
data['V_TYPE'] = np.where(data['V_TYPE'].isin(['01', '23']), 'car', data['V_TYPE'])
data['V_TYPE'].value_counts()/len(data)
car 0.824381 truck 0.070629 bike 0.044279 NN 0.038846 bus 0.012442 UU 0.005076 QQ 0.004346 Name: V_TYPE, dtype: float64
data = data[~data['V_TYPE'].isin(['QQ', 'UU'])]
data['V_TYPE'].value_counts()
car 3618710 truck 310035 bike 194368 NN 170521 bus 54615 Name: V_TYPE, dtype: int64
for i in list(data['V_TYPE'].unique()):
variable = 'V_TYPE'
#print('La distribución de la variable objetivo cuando,', variable, 'es igual a', i)
proporcion_fallecidos = pd.DataFrame(data['C_SEV'].value_counts()/len(data))
proporcion_fallecidos.columns= ['Target']
proporcion_fallecidos['Missing'] = data[data[variable].isin([i])]['C_SEV'].value_counts()/len(data[data[variable].isin([i])])
proporcion_fallecidos['Difference'] = proporcion_fallecidos['Missing'] - proporcion_fallecidos.Target
result = np.round(proporcion_fallecidos.iloc[1].Difference*100/proporcion_fallecidos.iloc[1].Target, 2)
if result < 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal disminuye un {np.abs(result)}% con respecto a la distribución de las fatalidades')
elif result > 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal aumenta un {result}% con respecto a la distribución de las fatalidades')
elif result == np.nan:
pass
print('')
print('-----------------------------')
print('')
Al ser la variable V_TYPE igual a car, la probabilidad de ser un accidente fatal disminuye un 14.9% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable V_TYPE igual a truck, la probabilidad de ser un accidente fatal aumenta un 105.52% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable V_TYPE igual a bus, la probabilidad de ser un accidente fatal aumenta un 73.43% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable V_TYPE igual a NN, la probabilidad de ser un accidente fatal aumenta un 70.4% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable V_TYPE igual a bike, la probabilidad de ser un accidente fatal aumenta un 26.64% con respecto a la distribución de las fatalidades -----------------------------
data['P_PSN'].value_counts()/len(data)
11 0.668542 13 0.151502 23 0.044335 21 0.037112 99 0.035943 22 0.015444 12 0.014982 UU 0.009838 96 0.007450 32 0.005104 QQ 0.004477 NN 0.002347 98 0.001126 33 0.000978 31 0.000788 97 0.000031 Name: P_PSN, dtype: float64
data['P_PSN'] = np.where(data['P_PSN'].isin(['11', '12', '13']), 'front', data['P_PSN'])
data['P_PSN'] = np.where(data['P_PSN'].isin(['21', '22', '23']), 'middle', data['P_PSN'])
data['P_PSN'] = np.where(data['P_PSN'].isin(['31', '32', '33']), 'back', data['P_PSN'])
data['P_PSN'] = np.where(data['P_PSN'].isin(['96']), 'occupant', data['P_PSN'])
data['P_PSN'] = np.where(data['P_PSN'].isin(['98', '97']), 'unsecure', data['P_PSN'])
data['P_PSN'] = np.where(data['P_PSN'].isin(['99']), 'pedestrian', data['P_PSN'])
data['P_PSN'].value_counts()/len(data)
front 0.835026 middle 0.096891 pedestrian 0.035943 UU 0.009838 occupant 0.007450 back 0.006871 QQ 0.004477 NN 0.002347 unsecure 0.001157 Name: P_PSN, dtype: float64
data['P_PSN'] = np.where(data['P_PSN'].isin(['UU', 'NN', 'QQ']), 'other', data['P_PSN'])
data['P_PSN'].value_counts()/len(data)
front 0.835026 middle 0.096891 pedestrian 0.035943 other 0.016662 occupant 0.007450 back 0.006871 unsecure 0.001157 Name: P_PSN, dtype: float64
for i in list(data['P_PSN'].unique()):
variable = 'P_PSN'
#print('La distribución de la variable objetivo cuando,', variable, 'es igual a', i)
proporcion_fallecidos = pd.DataFrame(data['C_SEV'].value_counts()/len(data))
proporcion_fallecidos.columns= ['Target']
proporcion_fallecidos['Missing'] = data[data[variable].isin([i])]['C_SEV'].value_counts()/len(data[data[variable].isin([i])])
proporcion_fallecidos['Difference'] = proporcion_fallecidos['Missing'] - proporcion_fallecidos.Target
result = np.round(proporcion_fallecidos.iloc[1].Difference*100/proporcion_fallecidos.iloc[1].Target, 2)
if result < 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal disminuye un {np.abs(result)}% con respecto a la distribución de las fatalidades')
elif result > 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal aumenta un {result}% con respecto a la distribución de las fatalidades')
elif result == np.nan:
pass
print('')
print('-----------------------------')
print('')
Al ser la variable P_PSN igual a front, la probabilidad de ser un accidente fatal disminuye un 8.78% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable P_PSN igual a middle, la probabilidad de ser un accidente fatal aumenta un 18.77% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable P_PSN igual a pedestrian, la probabilidad de ser un accidente fatal aumenta un 71.93% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable P_PSN igual a other, la probabilidad de ser un accidente fatal aumenta un 38.6% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable P_PSN igual a back, la probabilidad de ser un accidente fatal aumenta un 119.45% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable P_PSN igual a occupant, la probabilidad de ser un accidente fatal aumenta un 183.58% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable P_PSN igual a unsecure, la probabilidad de ser un accidente fatal aumenta un 81.81% con respecto a la distribución de las fatalidades -----------------------------
data['P_SAFE'].value_counts()/len(data)
02 0.713906 UU 0.103643 NN 0.095895 01 0.033800 13 0.025028 09 0.016528 QQ 0.008048 12 0.003134 10 0.000017 11 0.000002 Name: P_SAFE, dtype: float64
data['P_SAFE'] = np.where(data['P_SAFE'].isin(['02', '09', '11', '12']), 'safe', data['P_SAFE'])
data['P_SAFE'] = np.where(data['P_SAFE'].isin(['01', '10', '13']), 'unsafe', data['P_SAFE'])
data['P_SAFE'].value_counts()/len(data)
safe 0.733570 UU 0.103643 NN 0.095895 unsafe 0.058845 QQ 0.008048 Name: P_SAFE, dtype: float64
data['P_SAFE'] = np.where(data['P_SAFE'].isin(['QQ', 'NN', 'UU']), 'other', data['P_SAFE'])
data['P_SAFE'].value_counts()/len(data)
safe 0.733570 other 0.207585 unsafe 0.058845 Name: P_SAFE, dtype: float64
for i in list(data['P_SAFE'].unique()):
variable = 'P_SAFE'
#print('La distribución de la variable objetivo cuando,', variable, 'es igual a', i)
proporcion_fallecidos = pd.DataFrame(data['C_SEV'].value_counts()/len(data))
proporcion_fallecidos.columns= ['Target']
proporcion_fallecidos['Missing'] = data[data[variable].isin([i])]['C_SEV'].value_counts()/len(data[data[variable].isin([i])])
proporcion_fallecidos['Difference'] = proporcion_fallecidos['Missing'] - proporcion_fallecidos.Target
result = np.round(proporcion_fallecidos.iloc[1].Difference*100/proporcion_fallecidos.iloc[1].Target, 2)
if result < 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal disminuye un {np.abs(result)}% con respecto a la distribución de las fatalidades')
elif result > 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal aumenta un {result}% con respecto a la distribución de las fatalidades')
elif result == np.nan:
pass
print('')
print('-----------------------------')
print('')
Al ser la variable P_SAFE igual a safe, la probabilidad de ser un accidente fatal disminuye un 21.08% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable P_SAFE igual a other, la probabilidad de ser un accidente fatal aumenta un 4.72% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable P_SAFE igual a unsafe, la probabilidad de ser un accidente fatal aumenta un 246.1% con respecto a la distribución de las fatalidades -----------------------------
data['P_USER'].value_counts()/len(data)
1 0.630125 2 0.269129 3 0.037743 5 0.021161 4 0.021084 U 0.020757 Name: P_USER, dtype: float64
data['P_USER'] = np.where(data['P_USER'].isin(['1', '2']), 'vehicle', data['P_USER'])
data['P_USER'] = np.where(data['P_USER'].isin(['3']), 'pedestrian', data['P_USER'])
data['P_USER'] = np.where(data['P_USER'].isin(['4']), 'bicyclist', data['P_USER'])
data['P_USER'] = np.where(data['P_USER'].isin(['5']), 'motorcyclist', data['P_USER'])
data['P_USER'] = np.where(data['P_USER'].isin(['U']), 'other', data['P_USER'])
data['P_USER'].value_counts()/len(data)
vehicle 0.899255 pedestrian 0.037743 motorcyclist 0.021161 bicyclist 0.021084 other 0.020757 Name: P_USER, dtype: float64
for i in list(data['P_USER'].unique()):
variable = 'P_USER'
#print('La distribución de la variable objetivo cuando,', variable, 'es igual a', i)
proporcion_fallecidos = pd.DataFrame(data['C_SEV'].value_counts()/len(data))
proporcion_fallecidos.columns= ['Target']
proporcion_fallecidos['Missing'] = data[data[variable].isin([i])]['C_SEV'].value_counts()/len(data[data[variable].isin([i])])
proporcion_fallecidos['Difference'] = proporcion_fallecidos['Missing'] - proporcion_fallecidos.Target
result = np.round(proporcion_fallecidos.iloc[1].Difference*100/proporcion_fallecidos.iloc[1].Target, 2)
if result < 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal disminuye un {np.abs(result)}% con respecto a la distribución de las fatalidades')
elif result > 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal aumenta un {result}% con respecto a la distribución de las fatalidades')
elif result == np.nan:
pass
print('')
print('-----------------------------')
print('')
Al ser la variable P_USER igual a vehicle, la probabilidad de ser un accidente fatal disminuye un 5.26% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable P_USER igual a pedestrian, la probabilidad de ser un accidente fatal aumenta un 72.96% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable P_USER igual a other, la probabilidad de ser un accidente fatal aumenta un 68.37% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable P_USER igual a motorcyclist, la probabilidad de ser un accidente fatal aumenta un 79.03% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable P_USER igual a bicyclist, la probabilidad de ser un accidente fatal disminuye un 53.04% con respecto a la distribución de las fatalidades -----------------------------
data['P_SEX'].value_counts()/len(data)
M 0.540490 F 0.418658 U 0.038348 N 0.002504 Name: P_SEX, dtype: float64
data = data[~data['P_SEX'].isin(['N'])]
data['P_SEX'].value_counts()
M 2350184 F 1820431 U 166747 Name: P_SEX, dtype: int64
for i in list(data['P_SEX'].unique()):
variable = 'P_SEX'
#print('La distribución de la variable objetivo cuando,', variable, 'es igual a', i)
proporcion_fallecidos = pd.DataFrame(data['C_SEV'].value_counts()/len(data))
proporcion_fallecidos.columns= ['Target']
proporcion_fallecidos['Missing'] = data[data[variable].isin([i])]['C_SEV'].value_counts()/len(data[data[variable].isin([i])])
proporcion_fallecidos['Difference'] = proporcion_fallecidos['Missing'] - proporcion_fallecidos.Target
result = np.round(proporcion_fallecidos.iloc[1].Difference*100/proporcion_fallecidos.iloc[1].Target, 2)
if result < 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal disminuye un {np.abs(result)}% con respecto a la distribución de las fatalidades')
elif result > 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal aumenta un {result}% con respecto a la distribución de las fatalidades')
elif result == np.nan:
pass
print('')
print('-----------------------------')
print('')
Al ser la variable P_SEX igual a M, la probabilidad de ser un accidente fatal aumenta un 21.97% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable P_SEX igual a F, la probabilidad de ser un accidente fatal disminuye un 25.25% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable P_SEX igual a U, la probabilidad de ser un accidente fatal disminuye un 34.01% con respecto a la distribución de las fatalidades -----------------------------
data['V_YEAR'].value_counts()/len(data)
2000.0 5.499772e-02 1998.0 5.057613e-02 2002.0 5.035757e-02 1999.0 4.929702e-02 2003.0 4.785097e-02 2001.0 4.778642e-02 1997.0 4.506841e-02 2005.0 3.890890e-02 1995.0 3.875835e-02 2004.0 3.863224e-02 1996.0 3.412235e-02 1994.0 3.352844e-02 1992.0 3.299863e-02 2006.0 3.273764e-02 1993.0 3.206419e-02 2007.0 3.141771e-02 1991.0 2.896230e-02 1990.0 2.740053e-02 2008.0 2.515031e-02 1989.0 2.398716e-02 1988.0 2.092562e-02 2009.0 1.799181e-02 2010.0 1.565998e-02 1987.0 1.428956e-02 1986.0 1.196188e-02 2011.0 1.092945e-02 2012.0 8.711055e-03 1985.0 7.940080e-03 2013.0 5.981055e-03 1984.0 5.560292e-03 1983.0 3.264427e-03 1981.0 2.965627e-03 2014.0 2.442037e-03 1982.0 2.384399e-03 1980.0 2.015741e-03 1979.0 1.475090e-03 1978.0 1.028736e-03 1977.0 7.811200e-04 1976.0 4.906208e-04 1975.0 3.672739e-04 1974.0 2.750520e-04 1973.0 2.577604e-04 1972.0 2.360882e-04 2015.0 2.118799e-04 1970.0 1.620801e-04 1969.0 1.593134e-04 1971.0 1.429440e-04 1968.0 1.314163e-04 1967.0 1.141247e-04 1966.0 8.276920e-05 1965.0 7.078035e-05 1964.0 4.288321e-05 1963.0 3.227768e-05 1962.0 2.651381e-05 1960.0 2.282493e-05 1957.0 1.867495e-05 1939.0 1.590829e-05 1956.0 1.567773e-05 1961.0 1.337218e-05 1958.0 1.337218e-05 1959.0 1.337218e-05 1955.0 1.106663e-05 1950.0 8.069421e-06 1952.0 7.838866e-06 1947.0 7.377756e-06 1949.0 6.455537e-06 1930.0 6.224982e-06 1920.0 5.994427e-06 1953.0 5.763872e-06 1938.0 5.533317e-06 1951.0 5.533317e-06 1954.0 5.533317e-06 1948.0 4.841653e-06 1915.0 4.380543e-06 1931.0 4.380543e-06 1926.0 4.149988e-06 1940.0 3.919433e-06 1928.0 3.919433e-06 1946.0 3.919433e-06 1937.0 2.997214e-06 1935.0 2.766659e-06 1901.0 2.766659e-06 1922.0 2.766659e-06 1945.0 2.766659e-06 1944.0 2.766659e-06 1914.0 2.536104e-06 1923.0 2.536104e-06 1925.0 2.305549e-06 1941.0 2.305549e-06 1919.0 2.305549e-06 1932.0 2.074994e-06 1933.0 2.074994e-06 1918.0 2.074994e-06 1911.0 1.844439e-06 1929.0 1.844439e-06 1927.0 1.613884e-06 1903.0 1.613884e-06 1942.0 1.613884e-06 1912.0 1.613884e-06 1916.0 1.383329e-06 1921.0 1.383329e-06 1934.0 1.152774e-06 1908.0 1.152774e-06 1917.0 9.222195e-07 1913.0 9.222195e-07 1943.0 6.916647e-07 1924.0 6.916647e-07 1936.0 6.916647e-07 1905.0 4.611098e-07 1907.0 4.611098e-07 1906.0 2.305549e-07 1909.0 2.305549e-07 1910.0 2.305549e-07 Name: V_YEAR, dtype: float64
Lo que interesa en lugar de saber el año de fabricación de los autos, es la antigüedad que los mismos tenían en la fecha del accidente
data['V_ANT'] = data['C_YEAR'] - data['V_YEAR']
data.drop(columns=['V_YEAR'], inplace=True)
data['V_ANT'].value_counts()/len(data)
1.0 6.690196e-02 2.0 6.455998e-02 4.0 6.257052e-02 5.0 6.187171e-02 3.0 6.182099e-02 6.0 5.979233e-02 7.0 5.796865e-02 8.0 5.573687e-02 9.0 5.395561e-02 10.0 5.196131e-02 0.0 5.137685e-02 11.0 4.887717e-02 12.0 4.355343e-02 13.0 3.680117e-02 14.0 2.997513e-02 15.0 2.297018e-02 16.0 1.731398e-02 17.0 1.256593e-02 18.0 9.328712e-03 19.0 6.944313e-03 20.0 5.200857e-03 -1.0 5.175035e-03 21.0 3.855339e-03 22.0 2.884472e-03 23.0 2.190502e-03 24.0 1.597745e-03 25.0 1.211796e-03 26.0 9.678694e-04 27.0 7.232507e-04 28.0 5.498734e-04 29.0 4.749431e-04 30.0 3.924044e-04 31.0 3.216241e-04 32.0 2.556854e-04 33.0 1.994300e-04 34.0 1.752217e-04 35.0 1.191969e-04 36.0 1.025969e-04 37.0 8.853308e-05 38.0 7.423867e-05 40.0 6.340259e-05 39.0 6.271093e-05 41.0 5.418040e-05 42.0 3.942489e-05 43.0 3.688878e-05 44.0 3.550545e-05 45.0 2.651381e-05 46.0 1.913606e-05 47.0 1.890550e-05 48.0 1.498607e-05 -2.0 1.221941e-05 61.0 1.175830e-05 49.0 1.152774e-05 62.0 1.083608e-05 52.0 1.014441e-05 54.0 8.761086e-06 50.0 8.530531e-06 51.0 8.299976e-06 57.0 8.069421e-06 55.0 7.608311e-06 53.0 6.686092e-06 60.0 4.841653e-06 99.0 4.611098e-06 58.0 4.611098e-06 71.0 4.380543e-06 85.0 4.380543e-06 56.0 4.149988e-06 69.0 4.149988e-06 80.0 4.149988e-06 65.0 3.458323e-06 59.0 3.458323e-06 75.0 3.458323e-06 77.0 2.997214e-06 76.0 2.997214e-06 66.0 2.997214e-06 91.0 2.997214e-06 63.0 2.766659e-06 72.0 2.766659e-06 98.0 2.766659e-06 70.0 2.536104e-06 68.0 2.536104e-06 64.0 2.536104e-06 82.0 2.536104e-06 87.0 2.305549e-06 67.0 2.305549e-06 86.0 2.074994e-06 81.0 2.074994e-06 83.0 2.074994e-06 74.0 1.844439e-06 92.0 1.844439e-06 96.0 1.844439e-06 94.0 1.613884e-06 84.0 1.613884e-06 73.0 1.613884e-06 79.0 1.383329e-06 93.0 1.383329e-06 89.0 1.152774e-06 101.0 6.916647e-07 78.0 6.916647e-07 95.0 6.916647e-07 103.0 4.611098e-07 100.0 4.611098e-07 88.0 4.611098e-07 97.0 2.305549e-07 90.0 2.305549e-07 Name: V_ANT, dtype: float64
Observo valores negativos en la antigüedad de los autos, valores que serán filtrados en el dataset
data = data[(data['V_ANT'] > 0)|(data['V_ANT'].isna())]
data['V_ANT'].value_counts()
1.0 290178 2.0 280020 4.0 271391 5.0 268360 3.0 268140 6.0 259341 7.0 251431 8.0 241751 9.0 234025 10.0 225375 11.0 211998 12.0 188907 13.0 159620 14.0 130013 15.0 99630 16.0 75097 17.0 54503 18.0 40462 19.0 30120 20.0 22558 21.0 16722 22.0 12511 23.0 9501 24.0 6930 25.0 5256 26.0 4198 27.0 3137 28.0 2385 29.0 2060 30.0 1702 31.0 1395 32.0 1109 33.0 865 34.0 760 35.0 517 36.0 445 37.0 384 38.0 322 40.0 275 39.0 272 41.0 235 42.0 171 43.0 160 44.0 154 45.0 115 46.0 83 47.0 82 48.0 65 61.0 51 49.0 50 62.0 47 52.0 44 54.0 38 50.0 37 51.0 36 57.0 35 55.0 33 53.0 29 60.0 21 58.0 20 99.0 20 71.0 19 85.0 19 69.0 18 80.0 18 56.0 18 65.0 15 59.0 15 75.0 15 66.0 13 77.0 13 76.0 13 91.0 13 63.0 12 72.0 12 98.0 12 68.0 11 70.0 11 82.0 11 64.0 11 67.0 10 87.0 10 83.0 9 86.0 9 81.0 9 74.0 8 96.0 8 92.0 8 94.0 7 73.0 7 84.0 7 93.0 6 79.0 6 89.0 5 101.0 3 78.0 3 95.0 3 103.0 2 100.0 2 88.0 2 97.0 1 90.0 1 Name: V_ANT, dtype: int64
data['V_ANT'] = np.where((data['V_ANT'] > 25), 25, data['V_ANT'])
data['V_ANT'].value_counts()/len(data)
1.0 0.070913 2.0 0.068431 4.0 0.066322 5.0 0.065581 3.0 0.065527 6.0 0.063377 7.0 0.061444 8.0 0.059079 9.0 0.057191 10.0 0.055077 11.0 0.051808 12.0 0.046165 13.0 0.039008 14.0 0.031772 15.0 0.024347 16.0 0.018352 17.0 0.013319 18.0 0.009888 19.0 0.007361 25.0 0.006599 20.0 0.005513 21.0 0.004086 22.0 0.003057 23.0 0.002322 24.0 0.001694 Name: V_ANT, dtype: float64
data['C_CONF'].value_counts()/len(data)
21 0.300459 35 0.148645 06 0.088546 36 0.073768 33 0.072992 QQ 0.048507 04 0.036817 31 0.033388 22 0.033159 02 0.032370 UU 0.030448 03 0.028346 01 0.015914 41 0.013053 23 0.011899 34 0.010639 24 0.008899 32 0.008087 05 0.002157 25 0.001908 Name: C_CONF, dtype: float64
Con esta variable realizaremos un target encoding, las observaciones concuerdan a lo esperado.
Mantendremos las variables 'U' y 'Q' por separado dado que tienen un efecto contrario ante la variable objetivo.
for i in list(data['C_CONF'].unique()):
variable = 'C_CONF'
#print('La distribución de la variable objetivo cuando,', variable, 'es igual a', i)
proporcion_fallecidos = pd.DataFrame(data['C_SEV'].value_counts()/len(data))
proporcion_fallecidos.columns= ['Target']
proporcion_fallecidos['Missing'] = data[data[variable].isin([i])]['C_SEV'].value_counts()/len(data[data[variable].isin([i])])
proporcion_fallecidos['Difference'] = proporcion_fallecidos['Missing'] - proporcion_fallecidos.Target
result = np.round(proporcion_fallecidos.iloc[1].Difference*100/proporcion_fallecidos.iloc[1].Target, 2)
if result < 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal disminuye un {np.abs(result)}% con respecto a la distribución de las fatalidades')
elif result > 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal aumenta un {result}% con respecto a la distribución de las fatalidades')
elif result == np.nan:
pass
print('')
print('-----------------------------')
print('')
Al ser la variable C_CONF igual a 06, la probabilidad de ser un accidente fatal aumenta un 51.34% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a 35, la probabilidad de ser un accidente fatal disminuye un 17.87% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a 21, la probabilidad de ser un accidente fatal disminuye un 77.87% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a QQ, la probabilidad de ser un accidente fatal aumenta un 10.57% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a 31, la probabilidad de ser un accidente fatal aumenta un 568.03% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a 34, la probabilidad de ser un accidente fatal disminuye un 27.99% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a 22, la probabilidad de ser un accidente fatal disminuye un 19.68% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a 04, la probabilidad de ser un accidente fatal aumenta un 106.72% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a 02, la probabilidad de ser un accidente fatal aumenta un 44.59% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a 36, la probabilidad de ser un accidente fatal disminuye un 63.04% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a 33, la probabilidad de ser un accidente fatal disminuye un 40.84% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a UU, la probabilidad de ser un accidente fatal disminuye un 17.18% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a 32, la probabilidad de ser un accidente fatal aumenta un 121.8% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a 01, la probabilidad de ser un accidente fatal aumenta un 88.36% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a 25, la probabilidad de ser un accidente fatal disminuye un 40.33% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a 03, la probabilidad de ser un accidente fatal aumenta un 136.52% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a 41, la probabilidad de ser un accidente fatal aumenta un 9.35% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a 23, la probabilidad de ser un accidente fatal disminuye un 16.96% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a 24, la probabilidad de ser un accidente fatal disminuye un 49.98% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_CONF igual a 05, la probabilidad de ser un accidente fatal aumenta un 46.8% con respecto a la distribución de las fatalidades -----------------------------
data['C_RCFG'].value_counts()/len(data)
02 0.470274 01 0.353101 UU 0.085881 03 0.049737 QQ 0.024682 05 0.008731 04 0.004001 08 0.002022 06 0.001020 09 0.000283 07 0.000172 10 0.000096 Name: C_RCFG, dtype: float64
Agruparé observaciones que representan muy pocos datos en una variable 'OT'
data['C_RCFG'] = np.where((~data['C_RCFG'].isin(['02','01','UU','03','QQ','05'])), 'OT', data['C_RCFG'])
data['C_RCFG'].value_counts()/len(data)
02 0.470274 01 0.353101 UU 0.085881 03 0.049737 QQ 0.024682 05 0.008731 OT 0.007594 Name: C_RCFG, dtype: float64
Mismo tratamiento que la variable anterior
Con esta variable realizaremos un target encoding, las observaciones concuerdan a lo esperado.
Mantendremos las variables 'UU' y 'QQ' por separado dado que tienen un efecto contrario ante la variable objetivo.
for i in list(data['C_RCFG'].unique()):
variable = 'C_RCFG'
#print('La distribución de la variable objetivo cuando,', variable, 'es igual a', i)
proporcion_fallecidos = pd.DataFrame(data['C_SEV'].value_counts()/len(data))
proporcion_fallecidos.columns= ['Target']
proporcion_fallecidos['Missing'] = data[data[variable].isin([i])]['C_SEV'].value_counts()/len(data[data[variable].isin([i])])
proporcion_fallecidos['Difference'] = proporcion_fallecidos['Missing'] - proporcion_fallecidos.Target
result = np.round(proporcion_fallecidos.iloc[1].Difference*100/proporcion_fallecidos.iloc[1].Target, 2)
if result < 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal disminuye un {np.abs(result)}% con respecto a la distribución de las fatalidades')
elif result > 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal aumenta un {result}% con respecto a la distribución de las fatalidades')
elif result == np.nan:
pass
print('')
print('-----------------------------')
print('')
Al ser la variable C_RCFG igual a 01, la probabilidad de ser un accidente fatal aumenta un 65.54% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_RCFG igual a UU, la probabilidad de ser un accidente fatal disminuye un 29.78% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_RCFG igual a 02, la probabilidad de ser un accidente fatal disminuye un 41.91% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_RCFG igual a QQ, la probabilidad de ser un accidente fatal aumenta un 22.99% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_RCFG igual a OT, la probabilidad de ser un accidente fatal aumenta un 68.34% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_RCFG igual a 03, la probabilidad de ser un accidente fatal disminuye un 44.92% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_RCFG igual a 05, la probabilidad de ser un accidente fatal aumenta un 30.89% con respecto a la distribución de las fatalidades -----------------------------
data['C_WTHR'].value_counts()/len(data)
1 0.693974 2 0.103052 3 0.102722 4 0.060997 U 0.014778 6 0.014134 5 0.005189 7 0.002616 Q 0.002539 Name: C_WTHR, dtype: float64
Filtraremos a las observaciones 'U'dado que son muy poscas observaciones, además agruparemos a las observaciones 5, 6 y 7 en una adiocional llamada 'O'
data = data[~data['C_WTHR'].isin(['Q'])]
data['C_WTHR'] = np.where((data['C_WTHR'].isin(['5','6','7'])), 'O', data['C_WTHR'])
data['C_WTHR'].value_counts()/len(data)
1 0.695741 2 0.103314 3 0.102983 4 0.061152 O 0.021995 U 0.014815 Name: C_WTHR, dtype: float64
Mismo tratamiento que la variable anterior
Con esta variable realizaremos un target encoding, las observaciones concuerdan a lo esperado.
Mantendremos las variables 'U' por separado dado que tienen un efecto ante la variable objetivo.
for i in list(data['C_WTHR'].unique()):
variable = 'C_WTHR'
#print('La distribución de la variable objetivo cuando,', variable, 'es igual a', i)
proporcion_fallecidos = pd.DataFrame(data['C_SEV'].value_counts()/len(data))
proporcion_fallecidos.columns= ['Target']
proporcion_fallecidos['Missing'] = data[data[variable].isin([i])]['C_SEV'].value_counts()/len(data[data[variable].isin([i])])
proporcion_fallecidos['Difference'] = proporcion_fallecidos['Missing'] - proporcion_fallecidos.Target
result = np.round(proporcion_fallecidos.iloc[1].Difference*100/proporcion_fallecidos.iloc[1].Target, 2)
if result < 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal disminuye un {np.abs(result)}% con respecto a la distribución de las fatalidades')
elif result > 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal aumenta un {result}% con respecto a la distribución de las fatalidades')
elif result == np.nan:
pass
print('')
print('-----------------------------')
print('')
Al ser la variable C_WTHR igual a 3, la probabilidad de ser un accidente fatal disminuye un 18.1% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_WTHR igual a 1, la probabilidad de ser un accidente fatal disminuye un 5.16% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_WTHR igual a 2, la probabilidad de ser un accidente fatal aumenta un 25.19% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_WTHR igual a 4, la probabilidad de ser un accidente fatal aumenta un 13.78% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_WTHR igual a O, la probabilidad de ser un accidente fatal aumenta un 123.22% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_WTHR igual a U, la probabilidad de ser un accidente fatal disminuye un 47.56% con respecto a la distribución de las fatalidades -----------------------------
data['C_RSUR'].value_counts()/len(data)
1 0.654982 2 0.185218 5 0.055316 3 0.044750 Q 0.028448 U 0.013122 4 0.012532 6 0.004370 7 0.001017 8 0.000193 9 0.000052 Name: C_RSUR, dtype: float64
Agruparemos a las observaciones 9, 8, 7 y 6 en una adiocional llamada 'O'
data['C_RSUR'] = np.where((data['C_RSUR'].isin(['9','8','7', '6'])), 'O', data['C_RSUR'])
data['C_RSUR'].value_counts()/len(data)
1 0.654982 2 0.185218 5 0.055316 3 0.044750 Q 0.028448 U 0.013122 4 0.012532 O 0.005631 Name: C_RSUR, dtype: float64
Mismo tratamiento que la variable anterior
Con esta variable realizaremos un target encoding, las observaciones concuerdan a lo esperado.
Mantendremos las variablews 'U' y 'Q' por separado dado que tienen un efecto contrario ante la variable objetivo.
for i in list(data['C_RSUR'].unique()):
variable = 'C_RSUR'
#print('La distribución de la variable objetivo cuando,', variable, 'es igual a', i)
proporcion_fallecidos = pd.DataFrame(data['C_SEV'].value_counts()/len(data))
proporcion_fallecidos.columns= ['Target']
proporcion_fallecidos['Missing'] = data[data[variable].isin([i])]['C_SEV'].value_counts()/len(data[data[variable].isin([i])])
proporcion_fallecidos['Difference'] = proporcion_fallecidos['Missing'] - proporcion_fallecidos.Target
result = np.round(proporcion_fallecidos.iloc[1].Difference*100/proporcion_fallecidos.iloc[1].Target, 2)
if result < 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal disminuye un {np.abs(result)}% con respecto a la distribución de las fatalidades')
elif result > 0:
print(f'Al ser la variable {variable} igual a {i}, la probabilidad de ser un accidente fatal aumenta un {result}% con respecto a la distribución de las fatalidades')
elif result == np.nan:
pass
print('')
print('-----------------------------')
print('')
Al ser la variable C_RSUR igual a 2, la probabilidad de ser un accidente fatal disminuye un 14.75% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_RSUR igual a Q, la probabilidad de ser un accidente fatal aumenta un 14.89% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_RSUR igual a 1, la probabilidad de ser un accidente fatal aumenta un 0.94% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_RSUR igual a 3, la probabilidad de ser un accidente fatal aumenta un 9.78% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_RSUR igual a U, la probabilidad de ser un accidente fatal disminuye un 38.46% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_RSUR igual a 4, la probabilidad de ser un accidente fatal aumenta un 26.31% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_RSUR igual a 5, la probabilidad de ser un accidente fatal aumenta un 11.24% con respecto a la distribución de las fatalidades ----------------------------- Al ser la variable C_RSUR igual a O, la probabilidad de ser un accidente fatal aumenta un 143.68% con respecto a la distribución de las fatalidades -----------------------------
Obtengo las variables con missings y aplico un simple imputer (la primera idea fue aplicar una metodología de KKNImputer, pero por limitaciones computacionales, se propuso este imputador menos demandante de recursos).
data.isnull().sum()
C_YEAR 0 C_MNTH 216 C_WDAY 877 C_HOUR 41375 C_VEHS 0 C_CONF 0 C_RCFG 0 C_WTHR 0 C_RSUR 0 V_ID 27 V_TYPE 0 P_ID 29 P_SEX 0 P_AGE 255619 P_PSN 0 P_SAFE 0 P_USER 0 C_SEV 0 C_MNTH_UU 0 C_WDAY_U 0 C_HOUR_UU 0 P_ID_NN 0 P_ID_UU 0 V_ID_UU 0 V_YEAR_NNNN 0 V_YEAR_UUUU 0 P_AGE_NN 0 P_AGE_UU 0 V_ANT 415519 dtype: int64
data.drop(columns=['C_MNTH_UU', 'C_WDAY_U', 'C_HOUR_UU', 'P_ID_NN', 'P_ID_UU',
'V_ID_UU', 'P_AGE_NN'], inplace=True)
data.isnull().sum()
C_YEAR 0 C_MNTH 216 C_WDAY 877 C_HOUR 41375 C_VEHS 0 C_CONF 0 C_RCFG 0 C_WTHR 0 C_RSUR 0 V_ID 27 V_TYPE 0 P_ID 29 P_SEX 0 P_AGE 255619 P_PSN 0 P_SAFE 0 P_USER 0 C_SEV 0 V_YEAR_NNNN 0 V_YEAR_UUUU 0 P_AGE_UU 0 V_ANT 415519 dtype: int64
data.dropna(subset=['V_ID', 'P_ID'], inplace=True)
columns_with_na = ['C_MNTH', 'C_WDAY', 'C_HOUR', 'P_AGE', 'V_ANT']
data_to_fillna = data[columns_with_na]
imp = SimpleImputer(missing_values=np.nan, strategy='mean')
SimpleImputer_trained = imp.fit(data_to_fillna)
filename = '../models/SimpleImputer_trained.pickle'
pickle.dump(SimpleImputer_trained, open(filename, 'wb'))
data_to_fillna = SimpleImputer_trained.transform(data_to_fillna)
data[columns_with_na] = data_to_fillna
data.isnull().sum()
C_YEAR 0 C_MNTH 0 C_WDAY 0 C_HOUR 0 C_VEHS 0 C_CONF 0 C_RCFG 0 C_WTHR 0 C_RSUR 0 V_ID 0 V_TYPE 0 P_ID 0 P_SEX 0 P_AGE 0 P_PSN 0 P_SAFE 0 P_USER 0 C_SEV 0 V_YEAR_NNNN 0 V_YEAR_UUUU 0 P_AGE_UU 0 V_ANT 0 dtype: int64
Tranformamos a las horas, los dias de la semana y los meses en dos variables tomando el seno y el coseno de la variable, para captar el movimiento cíclico de la hora, ya que después de las 24 comienza un ciclo desde 0 a 24 nuevamente. Lo mismo con el resto de las variables
data['C_HOUR_SIN'] = np.sin(2 * np.pi * data['C_HOUR']/24)
data['C_HOUR_COS'] = np.cos(2 * np.pi * data['C_HOUR']/24)
data['C_WDAY_SIN'] = np.sin(2 * np.pi * data['C_WDAY']/7)
data['C_WDAY_COS'] = np.cos(2 * np.pi * data['C_WDAY']/7)
data['C_MNTH_SIN'] = np.sin(2 * np.pi * data['C_MNTH']/12)
data['C_MNTH_COS'] = np.cos(2 * np.pi * data['C_MNTH']/12)
data.drop(columns=['C_HOUR', 'C_WDAY', 'C_MNTH'], inplace=True)
df_selected = data[["C_HOUR_COS","C_HOUR_SIN"]].sample(1500).sort_index()
#display(df_selected)
fig = go.Figure()
fig.add_trace(go.Scatter(x=df_selected.C_HOUR_COS, y=df_selected.C_HOUR_SIN, mode="markers"))
fig.update_layout(xaxis = dict(title="C_HOUR_COS"),
yaxis = dict(title="C_HOUR_SIN", scaleanchor = "x", scaleratio = 1))
fig.show()
not_treated_columns = [c for c in data.columns if c not in ['C_HOUR_SIN', 'C_HOUR_COS', 'C_MNTH_SIN',
'C_MNTH_COS', 'C_WDAY_SIN', 'C_WDAY_COS',
'C_YEAR', 'C_AGE', 'V_ANT',
'C_SEV', 'V_YEAR_NNNN', 'V_YEAR_UUUU', 'P_AGE_UU',
'V_ID', 'P_ID', 'P_AGE']]
data[not_treated_columns].head()
| C_VEHS | C_CONF | C_RCFG | C_WTHR | C_RSUR | V_TYPE | P_SEX | P_PSN | P_SAFE | P_USER | |
|---|---|---|---|---|---|---|---|---|---|---|
| 4850824 | 03 | 06 | 01 | 3 | 2 | car | M | front | safe | vehicle |
| 3179371 | 02 | 35 | UU | 1 | Q | car | M | front | safe | vehicle |
| 5330174 | 02 | 21 | 01 | 1 | 1 | car | M | front | safe | vehicle |
| 4880251 | 02 | 21 | 01 | 1 | 1 | car | F | front | safe | vehicle |
| 3039624 | 02 | 21 | 02 | 1 | 1 | car | F | front | safe | vehicle |
data.drop(columns= ['V_ID', 'P_ID'], inplace=True)
TargetEncoder_model = TargetEncoder(cols=not_treated_columns)
TargetEncoder_res = TargetEncoder_model.fit(data, data['C_SEV'])
data = TargetEncoder_res.transform(data)
filename = '../models/TargetEncoder_model.pickle'
pickle.dump(TargetEncoder_res, open(filename, 'wb'))
data.head()
| C_YEAR | C_VEHS | C_CONF | C_RCFG | C_WTHR | C_RSUR | V_TYPE | P_SEX | P_AGE | P_PSN | ... | V_YEAR_NNNN | V_YEAR_UUUU | P_AGE_UU | V_ANT | C_HOUR_SIN | C_HOUR_COS | C_WDAY_SIN | C_WDAY_COS | C_MNTH_SIN | C_MNTH_COS | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 4850824 | 2011 | 0.013298 | 0.025305 | 0.027714 | 0.013715 | 0.014277 | 0.014307 | 0.020431 | 31.0 | 0.015287 | ... | 0 | 0 | 0 | 6.0 | 0.965926 | -2.588190e-01 | -0.433884 | -0.900969 | -0.866025 | 0.500000 |
| 3179371 | 2006 | 0.012907 | 0.013763 | 0.011817 | 0.015883 | 0.019240 | 0.014307 | 0.020431 | 44.0 | 0.015287 | ... | 0 | 0 | 0 | 3.0 | 0.707107 | -7.071068e-01 | -0.433884 | -0.900969 | -0.500000 | 0.866025 |
| 5330174 | 2013 | 0.012907 | 0.003711 | 0.027714 | 0.015883 | 0.016904 | 0.014307 | 0.020431 | 18.0 | 0.015287 | ... | 0 | 0 | 0 | 10.0 | -0.707107 | -7.071068e-01 | -0.974928 | -0.222521 | 0.866025 | -0.500000 |
| 4880251 | 2011 | 0.012907 | 0.003711 | 0.027714 | 0.015883 | 0.016904 | 0.014307 | 0.012568 | 27.0 | 0.015287 | ... | 0 | 0 | 0 | 11.0 | -1.000000 | -1.836970e-16 | -0.433884 | -0.900969 | -0.500000 | 0.866025 |
| 3039624 | 2006 | 0.012907 | 0.003711 | 0.009720 | 0.015883 | 0.016904 | 0.014307 | 0.012568 | 36.0 | 0.015287 | ... | 0 | 0 | 0 | 4.0 | -0.258819 | -9.659258e-01 | -0.433884 | -0.900969 | -0.500000 | -0.866025 |
5 rows × 23 columns
corr = data.corr(method = 'spearman')
plt.figure(figsize = (10, 8))
sns.heatmap(corr.abs(), cmap ='viridis' )
plt.show()
new_corr = corr.abs()
new_corr.loc[:,:] = np.tril(new_corr, k=-1) # below main lower triangle of an array
new_corr = new_corr.stack().to_frame('correlation').reset_index().sort_values(by='correlation', ascending=False)
new_corr[new_corr.correlation > 0.45]
| level_0 | level_1 | correlation | |
|---|---|---|---|
| 310 | V_YEAR_NNNN | P_USER | 0.467064 |
| 305 | V_YEAR_NNNN | V_TYPE | 0.460977 |
| 308 | V_YEAR_NNNN | P_PSN | 0.457356 |
Como podemos notar, no existen correlaciones significantes este las variables del Dataset.
Un punto para destacar es que no tenemos una variable que nos ayude a predecir en forma mayoritaria a la varaible 'C_SEV', es decir, el conjunto de datos como un todo realizarán un aporte equitativo para realizar las predicciones.
data.to_csv(r'../data/train_data_personal_prob.csv')